﻿Imports System.Net
Public Class IPv4
    ' Methods
    Public Sub New(ByVal IPAddress As String, ByVal Subnetmask As String)
        Me._GivenIPAddress = IPAddress
        Me._GivenSubnetmask = Subnetmask
        Me._IPAddressBytes = Me.GetIPAddressBytes(Me._GivenIPAddress)
        Me._SubnetmaskBytes = Me.GetSubnetmaskBytes(Me._GivenSubnetmask)
        Me._SubnetmaskInt = Me.GetSubnetmaskInInt(Me._SubnetmaskBytes)
        Me._MaxHosts = Me.GetMaxHosts(Me._SubnetmaskInt)
        If (Me._IPAddressBytes.Length <> Me._SubnetmaskBytes.Length) Then
            Throw New ArgumentException("Lengths of IP Address and Subnetmask do not match")
        End If
        Me._BroadcastAddress = Me.GetBroadcastAddress(Me._IPAddressBytes, Me._SubnetmaskBytes)
        Me._NetworkAddress = Me.GetNetworkAddress(Me._IPAddressBytes, Me._SubnetmaskBytes)
    End Sub

    Public Shared Function GetIPAddressRange(ByVal StartIPAddress As IPAddress, EndIPAddress As IPAddress) As List(Of IPAddress)

        Dim IPAddressRange As List(Of IPAddress) = New List(Of IPAddress)
        Dim byteStartIPAddress() As Byte = StartIPAddress.GetAddressBytes
        Array.Reverse(byteStartIPAddress)
        Dim byteEndIPAddress() As Byte = EndIPAddress.GetAddressBytes
        Array.Reverse(byteEndIPAddress)
        Dim uintStartIPAddres As UInt32 = BitConverter.ToUInt32(byteStartIPAddress, 0)
        Dim uintEndIPAddress As UInt32 = BitConverter.ToUInt32(byteEndIPAddress, 0)
        If uintEndIPAddress <= uintStartIPAddres Then
            Throw New ArgumentException("EndIPAddress is less or equal StartIPAddress")
        End If
        For uintIPAddress As UInt32 = uintStartIPAddres To uintEndIPAddress
            Dim byteIPAddress() As Byte = BitConverter.GetBytes(uintIPAddress)
            Array.Reverse(byteIPAddress)
            Dim _IPAddress As New IPAddress(byteIPAddress)
            IPAddressRange.Add(_IPAddress)
        Next
        GetIPAddressRange = IPAddressRange

    End Function

    Private Function GetBroadcastAddress(ByVal _IPAddressBytes As Byte(), ByVal _SubnetmaskBytes As Byte()) As IPAddress
        Dim address As Byte() = New Byte(_IPAddressBytes.Length - 1) {}
        Dim i As Integer
        For i = 0 To address.Length - 1
            address(i) = CByte((_IPAddressBytes(i) Or (_SubnetmaskBytes(i) Xor &HFF)))
        Next i
        Return New IPAddress(address)
    End Function

    Private Function GetIPAddressBytes(ByVal IPAddress As String) As Byte()
        Dim addressBytes As Byte()
        Try
            addressBytes = System.Net.IPAddress.Parse(IPAddress).GetAddressBytes
        Catch ex As Exception
            Throw New ArgumentException("The given String is not an IP Address")
        End Try
        Return addressBytes
    End Function

    Private Function GetMaxHosts(ByVal SubnetmaskInt As Integer) As Integer
        Dim num As Integer = (&H20 - SubnetmaskInt)
        Return (CInt(Math.Pow(2, Convert.ToDouble(num))) - 2)
    End Function

    Private Function GetNetworkAddress(ByVal _IPAddressBytes As Byte(), ByVal _SubnetmaskBytes As Byte()) As IPAddress
        Dim address As Byte() = New Byte(_IPAddressBytes.Length - 1) {}
        Dim i As Integer
        For i = 0 To address.Length - 1
            address(i) = CByte((_IPAddressBytes(i) And _SubnetmaskBytes(i)))
        Next i
        Return New IPAddress(address)
    End Function

    Public Function GetNetworkRange() As IPAddress()
        Dim addressBytes As Byte() = Me._NetworkAddress.GetAddressBytes
        Dim num As Integer = Convert.ToInt32(addressBytes(0))
        Dim num2 As Integer = Convert.ToInt32(addressBytes(1))
        Dim num3 As Integer = Convert.ToInt32(addressBytes(2))
        Dim num4 As Integer = (Convert.ToInt32(addressBytes(3)) + 1)
        Dim addressArray As IPAddress() = New IPAddress(Me._MaxHosts - 1) {}
        addressArray(0) = IPAddress.Parse(Convert.ToString(String.Concat(New Object() {num, ".", num2, ".", num3, ".", num4})))
        Dim i As Integer
        For i = 1 To Me._MaxHosts - 1
            If (num4 < &HFF) Then
                num4 += 1
            ElseIf ((num4 = &HFF) AndAlso (num3 < &HFF)) Then
                num3 += 1
                num4 = 0
            ElseIf (((num4 = &HFF) AndAlso (num3 = &HFF)) AndAlso (num2 < &HFF)) Then
                num2 += 1
                num3 = 0
                num4 = 0
            Else
                If ((((num4 <> &HFF) OrElse (num3 <> &HFF)) OrElse (num2 <> &HFF)) OrElse (num >= &HFF)) Then
                    Throw New ArgumentOutOfRangeException
                End If
                num += 1
                num2 = 0
                num3 = 0
                num4 = 0
            End If
            Dim ipString As String = Convert.ToString(String.Concat(New Object() {num, ".", num2, ".", num3, ".", num4}))
            addressArray(i) = IPAddress.Parse(ipString)
        Next i
        Return addressArray
    End Function

    Public Function GetNetworkRange(ByVal FirstAddress As IPAddress, ByVal Count As Integer) As IPAddress()
        If (Count > Me._MaxHosts) Then
            Throw New ArgumentOutOfRangeException("Count", "")
        End If
        Dim addressBytes As Byte() = FirstAddress.GetAddressBytes
        Dim num As Integer = Convert.ToInt32(addressBytes(0))
        Dim num2 As Integer = Convert.ToInt32(addressBytes(1))
        Dim num3 As Integer = Convert.ToInt32(addressBytes(2))
        Dim num4 As Integer = Convert.ToInt32(addressBytes(3))
        Dim addressArray As IPAddress() = New IPAddress(Count - 1) {}
        addressArray(0) = IPAddress.Parse(Convert.ToString(String.Concat(New Object() {num, ".", num2, ".", num3, ".", num4})))
        Dim i As Integer = 1
        Do While (i <= Count)
            If (num4 < &HFF) Then
                num4 += 1
            ElseIf ((num4 = &HFF) AndAlso (num3 < &HFF)) Then
                num3 += 1
                num4 = 0
            ElseIf (((num4 = &HFF) AndAlso (num3 = &HFF)) AndAlso (num2 < &HFF)) Then
                num2 += 1
                num3 = 0
                num4 = 0
            Else
                If ((((num4 <> &HFF) OrElse (num3 <> &HFF)) OrElse (num2 <> &HFF)) OrElse (num >= &HFF)) Then
                    Throw New ArgumentOutOfRangeException
                End If
                num += 1
                num2 = 0
                num3 = 0
                num4 = 0
            End If
            Dim iPAddress As String = Convert.ToString(String.Concat(New Object() {num, ".", num2, ".", num3, ".", num4}))
            If Not Me.IsInSameSubnet(iPAddress, Me._GivenSubnetmask) Then
                Throw New ArgumentOutOfRangeException("Count", "")
            End If
            addressArray(i) = System.Net.IPAddress.Parse(iPAddress)
            i += 1
        Loop
        Return addressArray
    End Function

    Public Function GetNetworkRange(ByVal FirstAddress As IPAddress, ByVal LastAddress As IPAddress) As IPAddress()
        If (Not Me.IsInSameSubnet(FirstAddress.ToString, Me._GivenSubnetmask) OrElse Not Me.IsInSameSubnet(LastAddress.ToString, Me._GivenSubnetmask)) Then
            Throw New ArgumentException("The given IP Addresses are not in the same Subnet how the master IP")
        End If
        Dim addressBytes As Byte() = FirstAddress.GetAddressBytes
        Dim buffer2 As Byte() = LastAddress.GetAddressBytes
        Dim flag As Boolean = False
        If ((((((addressBytes(0) >= buffer2(0)) OrElse (addressBytes(1) > buffer2(1))) OrElse (addressBytes(2) > buffer2(2))) OrElse (addressBytes(3) > buffer2(3))) AndAlso (((addressBytes(1) >= buffer2(1)) OrElse (addressBytes(2) > buffer2(2))) OrElse (addressBytes(3) > buffer2(3)))) AndAlso (((addressBytes(2) >= buffer2(2)) OrElse (addressBytes(3) > buffer2(3))) AndAlso (addressBytes(3) >= buffer2(3)))) Then
            If ((((addressBytes(0) <> buffer2(0)) OrElse (addressBytes(1) <> buffer2(1))) OrElse (addressBytes(2) <> buffer2(2))) OrElse (addressBytes(3) <> buffer2(3))) Then
                Throw New ArgumentException
            End If
            flag = True
        End If
        Dim num As Integer = Convert.ToInt32(addressBytes(0))
        Dim num2 As Integer = Convert.ToInt32(addressBytes(1))
        Dim num3 As Integer = Convert.ToInt32(addressBytes(2))
        Dim num4 As Integer = Convert.ToInt32(addressBytes(3))
        Dim num5 As Integer = Convert.ToInt32(buffer2(0))
        Dim num6 As Integer = Convert.ToInt32(buffer2(1))
        Dim num7 As Integer = Convert.ToInt32(buffer2(2))
        Dim num8 As Integer = Convert.ToInt32(buffer2(3))
        Dim list As New List(Of IPAddress) From {IPAddress.Parse(Convert.ToString(String.Concat(New Object() {num, ".", num2, ".", num3, ".", num4})))}
        If Not flag Then
            Dim flag2 As Boolean = True
            Do While flag2
                If (num4 < &HFF) Then
                    num4 += 1
                ElseIf ((num4 = &HFF) AndAlso (num3 < &HFF)) Then
                    num3 += 1
                    num4 = 0
                ElseIf (((num4 = &HFF) AndAlso (num3 = &HFF)) AndAlso (num2 < &HFF)) Then
                    num2 += 1
                    num3 = 0
                    num4 = 0
                Else
                    If ((((num4 <> &HFF) OrElse (num3 <> &HFF)) OrElse (num2 <> &HFF)) OrElse (num >= &HFF)) Then
                        Throw New ArgumentOutOfRangeException
                    End If
                    num += 1
                    num2 = 0
                    num3 = 0
                    num4 = 0
                End If
                Dim ipString As String = Convert.ToString(String.Concat(New Object() {num, ".", num2, ".", num3, ".", num4}))
                list.Add(IPAddress.Parse(ipString))
                If ((((num = num5) AndAlso (num2 = num6)) AndAlso (num3 = num7)) AndAlso (num4 = num8)) Then
                    flag2 = False
                End If
            Loop
        End If
        Dim addressArray As IPAddress() = New IPAddress(list.Count - 1) {}
        Dim i As Integer
        For i = 0 To list.Count - 1
            addressArray(i) = list.Item(i)
        Next i
        Return addressArray
    End Function

    Private Function GetSubnetmaskBytes(ByVal Subnetmask As String) As Byte()
        Dim buffer2 As Byte()
        Try
            Dim addressBytes As Byte() = IPAddress.Parse(Subnetmask).GetAddressBytes
            Dim flag As Boolean = False
            Dim i As Integer
            For i = 0 To addressBytes.Length - 1
                If ((addressBytes(i) <> &HFF) OrElse flag) Then
                    If Not ((addressBytes(i) = &HFF) OrElse flag) Then
                        flag = True
                    ElseIf ((addressBytes(i) <> 0) OrElse Not flag) Then
                        Throw New ArgumentException
                    End If
                End If
            Next i
            buffer2 = addressBytes
        Catch ex As Exception
            Throw New ArgumentException("The given String is not an Subnetmask")
        End Try
        Return buffer2
    End Function

    Private Function GetSubnetmaskInInt(ByVal SubnetmaskBytes As Byte()) As Integer
        Dim chArray As Char() = ((Convert.ToString(SubnetmaskBytes(0), 2) & Convert.ToString(SubnetmaskBytes(1), 2)) & Convert.ToString(SubnetmaskBytes(2), 2) & Convert.ToString(SubnetmaskBytes(3), 2)).ToCharArray
        Dim length As Integer = chArray.Length
        Dim i As Integer
        For i = 0 To chArray.Length - 1
            If (chArray(i) = "0"c) Then
                length -= 1
            End If
        Next i
        Return length
    End Function

    Public Function IsInSameSubnet(ByVal IPAddress As IPv4) As Boolean
        Return IPAddress.NetworkAddress.Equals(Me._NetworkAddress)
    End Function

    Public Function IsInSameSubnet(ByVal IPAddress As String, ByVal Subnetmask As String) As Boolean
        Return Me.GetNetworkAddress(Me.GetIPAddressBytes(IPAddress), Me.GetSubnetmaskBytes(Subnetmask)).Equals(Me._NetworkAddress)
    End Function


    ' Properties
    Public ReadOnly Property BroadcastAddress As IPAddress
        Get
            Return Me._BroadcastAddress
        End Get
    End Property

    Public ReadOnly Property GivenIPAddress As String
        Get
            Return Me._GivenIPAddress
        End Get
    End Property

    Public ReadOnly Property GivenSubnetmask As String
        Get
            Return Me._GivenSubnetmask
        End Get
    End Property

    Public ReadOnly Property IPAddress As IPAddress
        Get
            Return IPAddress.Parse(Me._GivenIPAddress)
        End Get
    End Property

    Public ReadOnly Property MaxHosts As Integer
        Get
            Return Me._MaxHosts
        End Get
    End Property

    Public ReadOnly Property NetworkAddress As IPAddress
        Get
            Return Me._NetworkAddress
        End Get
    End Property

    Public ReadOnly Property SubnetmaskInt As Integer
        Get
            Return Me._SubnetmaskInt
        End Get
    End Property


    ' Fields
    Private _BroadcastAddress As IPAddress
    Private _GivenIPAddress As String
    Private _GivenSubnetmask As String
    Private _IPAddressBytes As Byte()
    Private _MaxHosts As Integer
    Private _NetworkAddress As IPAddress
    Private _SubnetmaskBytes As Byte()
    Private _SubnetmaskInt As Integer
End Class



